package de.koller.million.render;

import Jama.Matrix;
import de.koller.oceanFramework.math.Vec3;
import de.koller.oceanFramework.tree.Mother;
import de.koller.oceanFramework.tree.Sea3X;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.GL11;

public class Camera extends Sea3X {

	@Mother private RenderRoot rroot;
	
	private final Vec3 position = new Vec3( 0, 1, 0 );
	private float rotX = 0;
	private float rotY = 0;
	private float flyspeed = 0.1f;

	@Override
	protected void init() {
		super.init();
		
		rroot.input.grabMouse();
	}
	
	@Override
	protected void update( int elapsedTime ) {
		super.update( elapsedTime );
		
		rotY += rroot.input.getMouseDX() * 0.1f;
		rotX += rroot.input.getMouseDY() * 0.1f;
		
		float mx = 0, my = 0, mz = 0;
		
		mz += rroot.input.isKeyDown( Keyboard.KEY_W ) ? -1 : 0;
		mz += rroot.input.isKeyDown( Keyboard.KEY_S ) ?  1 : 0;
		
		mx += rroot.input.isKeyDown( Keyboard.KEY_A ) ? -1 : 0;
		mx += rroot.input.isKeyDown( Keyboard.KEY_D ) ?  1 : 0;
		
		my += rroot.input.isKeyDown( Keyboard.KEY_Q ) ?  1 : 0;
		my += rroot.input.isKeyDown( Keyboard.KEY_E ) ? -1 : 0;
		
		Vec3 mv = new Vec3( mx, my, mz );
		if( !(mx == 0 && my == 0 && mz == 0) )
			mv.setLength( 1 );
		
		double cosX = Math.cos( Math.toRadians( rotX ) );
		double sinX = Math.sin( Math.toRadians( rotX ) );
		double cosY = Math.cos( Math.toRadians( rotY ) );
		double sinY = Math.sin( Math.toRadians( rotY ) );
		
		Matrix rx = new Matrix( new double[][] {{ 1,    0,     0 }, 
												{ 0, cosX, -sinX }, 
												{ 0, sinX,  cosX } } ).transpose();
		
		Matrix ry = new Matrix( new double[][] {{  cosY, 0, sinY }, 
												{     0, 1,    0 }, 
												{ -sinY, 0, cosY } } ).transpose();
		
		Matrix m = ry.times( rx );
		m = m.times( new Matrix( new double[][] {{mv.getX()},{mv.getY()},{mv.getZ()}} ) );
		
		position.add( m.get(0,0)*flyspeed, m.get(1,0)*flyspeed, m.get(2,0)*flyspeed );
	}

	public void preTransform() {
		GL11.glPushMatrix();
		GL11.glRotatef( rotX, 1, 0, 0 );
		GL11.glRotatef( rotY, 0, 1, 0 );
		GL11.glTranslated( -position.getX(), -position.getY(), -position.getZ() );
	}
	
	public void postTransform() {
		GL11.glPopMatrix();
	}

	public Vec3 getPosition() {
		return position;
	}

	public float getRotX() {
		return rotX;
	}

	public float getRotY() {
		return rotY;
	}

	public void setRotX( float rotX ) {
		this.rotX = rotX;
	}

	public void setRotY( float rotY ) {
		this.rotY = rotY;
	}
	
}
